/*******************************************************************************
Johnathon Trumble
Module 6
Group 3

Creation Date: November 17th, 2008

File name: IO.C
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include "mpx_supt.h"
#include "pcb.h"
#include "int_supt.h"
#include "r3_supt.h"
#include "IO_SUPT.H"

struct IOCB IOCB1[NUM_DEVICES];
struct IOD *wait;
struct IOD *insrt;

int ioscheduler(PCB *pcb_req, int dev_id, int op_code, char *bufferaddress, int *countaddress){
    
    if(pcb_req == NULL)
       return 1;
    if((op_code != READ) && (op_code != WRITE))
       return 1;
    
    switch(dev_id){
       case TERMINAL:
            if(IOCB1[TERMINAL-1].current == NULL){
                IOCB1[TERMINAL-1].current= pcb_req;
                IOCB1[TERMINAL-1].buffer= bufferaddress;
                IOCB1[TERMINAL-1].length= countaddress;
            
                if(op_code == READ)
                   trm_read(IOCB1[TERMINAL-1].buffer, IOCB1[TERMINAL-1].length);
                if(op_code == WRITE)
                   trm_write(IOCB1[TERMINAL-1].buffer, IOCB1[TERMINAL-1].length);
            }
            else{
                wait = (struct IOD*)(sys_alloc_mem(sizeof(struct IOD)));
                
                (*wait).current = pcb_req;
                (*wait).buffer = bufferaddress;
                (*wait).length = countaddress;
                (*wait).op_code = op_code;
                (*wait).next = NULL;
                
                if(IOCB1[TERMINAL-1].next == NULL){
                   IOCB1[TERMINAL-1].next = wait;
                   }
                else{
                   insrt = IOCB1[TERMINAL-1].next;
                   while((*insrt).next != NULL){
                      insrt = (*insrt).next;
                      }
                   (*insrt).next = wait;
                }
            }
            break;
            case COM_PORT:
            if(IOCB1[COM_PORT-1].current == NULL){
                IOCB1[COM_PORT-1].current= pcb_req;
                IOCB1[COM_PORT-1].buffer= bufferaddress;
                IOCB1[COM_PORT-1].length= countaddress;
            
                if(op_code == READ)
                   trm_read(IOCB1[COM_PORT-1].buffer, IOCB1[COM_PORT-1].length);
                if(op_code == WRITE)
                   trm_write(IOCB1[COM_PORT-1].buffer, IOCB1[COM_PORT-1].length);
            }
            else{
                wait = (struct IOD*)(sys_alloc_mem(sizeof(struct IOD)));
                
                (*wait).current = pcb_req;
                (*wait).buffer = bufferaddress;
                (*wait).length = countaddress;
                (*wait).op_code = op_code;
                (*wait).next = NULL;
                
                if(IOCB1[COM_PORT-1].next == NULL){
                   IOCB1[COM_PORT-1].next = wait;
                   }
                else{
                   insrt = IOCB1[COM_PORT-1].next;
                   while((*insrt).next != NULL){
                      insrt = (*insrt).next;
                      }
                   (*insrt).next = wait;
                }
            }
            break;
       }
    blockPCB(pcb_req);   
    
}
